﻿using System;
using System.Collections.Generic;
using System.Data;
using MySql.Data;
using MySql.Data.MySqlClient;
using Eb;
using Es;

public class MySQLRequest
{
    public string sql;
    public bool non_query;
    public Dictionary<string, string> map_param;
    public OnMySQLExecuteNonQuery cb_nonquery;
    public OnMySQLExecuteReader cb_reader;
    public MySqlConnection con;
    public MySqlCommand cmd;
    public MySQLResult result;
    public DataTable dt;
    public IAsyncResult r;
}

public class DbMySQL : IDbMySQL
{
    //-------------------------------------------------------------------------
    Queue<MySQLRequest> mQueRequest = new Queue<MySQLRequest>();

    //-------------------------------------------------------------------------
    public ILog Log { get; private set; }
    public string ConStr { get; private set; }
    public Queue<MySQLRequest> AllRequest { get; private set; }
    public HashSet<MySQLRequest> CurRequest { get; private set; }

    //-------------------------------------------------------------------------
    public void setup(string connection_str)
    {
        Log = EbLogFactory.GetLog(this.GetType().Name);
        ConStr = connection_str;
        AllRequest = new Queue<MySQLRequest>();
        CurRequest = new HashSet<MySQLRequest>();
    }

    //---------------------------------------------------------------------
    public void update(float elapsed_tm)
    {
        while (AllRequest.Count > 0 && CurRequest.Count < 10)
        {
            var request = AllRequest.Dequeue();
            CurRequest.Add(request);
        }

        foreach (var i in CurRequest)
        {
            try
            {
                _excuteOneCommand(i);
            }
            catch (Exception ex)
            {
                Log.Error("DbMySQLStateWork.evUpdate() Exception: " + ex);
            }
        }

        while (mQueRequest.Count > 0)
        {
            MySQLRequest request = mQueRequest.Dequeue();
            CurRequest.Remove(request);

            if (request.non_query && request.cb_nonquery != null)
            {
                request.cb_nonquery(request.result, request.map_param);
            }
            else if (!request.non_query && request.cb_reader != null)
            {
                request.cb_reader(request.result, request.dt, request.map_param);
            }
        }
    }

    //---------------------------------------------------------------------
    public void asyncExecuteNonQuery(OnMySQLExecuteNonQuery cb, string sql, Dictionary<string, string> map_param)
    {
        MySQLRequest request = new MySQLRequest();
        request.sql = sql;
        request.non_query = true;
        request.map_param = map_param;
        request.cb_nonquery = cb;
        request.cb_reader = null;

        request.con = null;
        request.cmd = null;
        request.result = MySQLResult.Failed;
        request.dt = null;
        request.r = null;
        AllRequest.Enqueue(request);
    }

    //---------------------------------------------------------------------
    public void asyncExecuteReader(OnMySQLExecuteReader cb, string sql, Dictionary<string, string> map_param)
    {
        MySQLRequest request = new MySQLRequest();
        request.sql = sql;
        request.non_query = false;
        request.map_param = map_param;
        request.cb_nonquery = null;
        request.cb_reader = cb;

        request.con = null;
        request.cmd = null;
        request.result = MySQLResult.Failed;
        request.dt = null;
        request.r = null;
        AllRequest.Enqueue(request);
    }

    //-------------------------------------------------------------------------
    void _excuteOneCommand(MySQLRequest request)
    {
        if (request.r == null)
        {
            if (request.con == null)
            {
                request.con = new MySqlConnection(ConStr);
                request.con.Open();
            }

            if (request.cmd == null)
            {
                request.cmd = request.con.CreateCommand();
                request.cmd.CommandText = request.sql;
            }

            if (request.non_query) request.r = request.cmd.BeginExecuteNonQuery();
            else request.r = request.cmd.BeginExecuteReader();
        }

        if (request.r.IsCompleted)
        {
            mQueRequest.Enqueue(request);

            if (request.non_query)
            {
                int count = request.cmd.EndExecuteNonQuery(request.r);
                request.result = MySQLResult.Success;
            }
            else
            {
                DataTable dt = null;
                using (MySqlDataReader reader = request.cmd.EndExecuteReader(request.r))
                {
                    dt = new DataTable();
                    dt.Load(reader);
                }
                request.result = MySQLResult.Success;
                request.dt = dt;

                Log.Info("DbMySQLStateWork.evUpdate() sql执行完成，sql=" + request.sql);
            }

            //request.con.Close();
            //request.cmd.Dispose();
            //request.cmd = null;

            request.con.Dispose();
            request.cmd.Dispose();
            request.con = null;
            request.cmd = null;

        }
    }
}
